'use strict'

const {parse} = require('@babel/parser');
const traverse = require('D:/WorkSpace/js_obscure_reducation/node_modules/@babel/traverse').default;
const types = require('@babel/types');
const generator = require('D:/WorkSpace/js_obscure_reducation/node_modules/@babel/generator').default;

let code = `function squire(i){    // FunctionDeclaration.params.name = i, 函数声明的时候为在函数作用域中为形参创建变量（绑定），绑定就是创建变量{kind: 'param'}
    return i*i*i;    // BinarryExpression.left.name = i, 二元表达式运算时会使用到变量，引用就是使用变量
}
function i(){
    var i = 123;    // VariableDeclarator.id.name = i, 变量声明时，在函数作用域中创建变量（绑定）{kind: 'var'}
    i += 2;    // AssignmentExpression.left.name = i, 赋值表达式是为变量a重新赋值，也即被修改了一次{violations：1}，但是没有使用{references: 0}
    return 123;
}`

let ast = parse(code);

const visitor = {
    FunctionDeclaration:{
        enter: function(path){
            console.log('这里是函数申明：'+path.get('id').node.name+'()')
            path.scope.dump();
        //     for(let x in path.scope.bindings){
        //         console.log(x);
        //         for(let y in path.scope.bindings[x].referencePaths){
        //             let z = path.scope.bindings[x].referencePaths[y];
        //             console.log(z.parentPath.toString());
        //        }              
        //    }
        },
    },
}

traverse(ast, visitor);
/* 虽然绑定为变量名-运行时对象的关联，但是Babel遍历时尚无运行，此不矛盾？Babel中的变量绑定就可以直接理解为在作用域中对一个变量的创建。
而对一个binding的属性计算是通过具体节点类型来判断的，如 BinaryExpression, AssignmentExpression .et。更可以猜测是用的enter()计算出的I属性
这里是函数申明：squire()
------------------------------------------------------------
# FunctionDeclaration
 - i { constant: true, references: 3, violations: 0, kind: 'param' }
# Program
 - squire { constant: true, references: 0, violations: 0, kind: 'hoisted' }
 - i { constant: true, references: 0, violations: 0, kind: 'hoisted' }
------------------------------------------------------------
这里是函数申明：i()
------------------------------------------------------------
# FunctionDeclaration
 - i { constant: false, references: 0, violations: 1, kind: 'var' }
# Program
 - squire { constant: true, references: 0, violations: 0, kind: 'hoisted' }
 - i { constant: true, references: 0, violations: 0, kind: 'hoisted' }
------------------------------------------------------------
*/
